package com.pilgrim.framework.common.util;

import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.tika.metadata.HttpHeaders;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaMetadataKeys;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.xml.sax.helpers.DefaultHandler;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Objects;

/**
 * DesUtil
 *
 * @author wyb
 * @version 1.0.0
 */
@Slf4j
public class FileUtils {

    public static final String FILE_TYPE_IMAGE = "image";

    /**
     * 创建缩略图
     *
     * @param inputStream 文件流
     * @return 缩略图片
     */
    public static BufferedImage createThumbnail(InputStream inputStream) {
        try {
            return Thumbnails.of(inputStream).scale(1D).outputQuality(0.75F).asBufferedImage();
        } catch (IOException e) {
            log.warn("创建缩略图异常：", e);
        }
        return null;
    }

    /**
     * 创建缩略图
     *
     * @param bufferedImage 文件流
     * @param filePath 文件保存路径
     */
    public static void createThumbnail(BufferedImage bufferedImage, String filePath) {
        try {
            Thumbnails.of(bufferedImage).scale(1D).outputQuality(0.75F).toFile(filePath);
        } catch (IOException e) {
            log.warn("创建缩略图异常：", e);
        }
    }

    /**
     * 判断文件是否是图片
     *
     * @param inputStream 文件流
     * @param fileName    文件名称
     * @return 是否是图片
     */
    public static boolean isImage(InputStream inputStream, String fileName) {
        String mimeType = getMimeType(inputStream, fileName);
        if (mimeType == null || mimeType.isEmpty()) {
            return Boolean.FALSE;
        }
        return mimeType.startsWith(FILE_TYPE_IMAGE);
    }

    /**
     * 判断文件是否是图片
     *
     * @param file 文件
     * @return 是否是图片
     */
    public static boolean isImage(File file) {
        String mimeType = getMimeType(file);
        if (mimeType == null || mimeType.isEmpty()) {
            return Boolean.FALSE;
        }
        return mimeType.startsWith(FILE_TYPE_IMAGE);
    }

    /**
     * 获取文件类型
     *
     * @param filePath 文件路径
     * @return 文件类型
     */
    public static String getMimeType(String filePath) {
        if (filePath == null || filePath.isEmpty()) {
            return null;
        }
        File file = new File(filePath);
        if (file.exists()) {
            return getMimeType(file);
        }
        return null;
    }

    /**
     * 获取文件类型
     *
     * @param file 文件
     * @return 文件类型
     */
    public static String getMimeType(File file) {
        try {
            if (file.isDirectory()) {
                return null;
            }
            return getMimeType(new FileInputStream(file), file.getName());
        } catch (Exception e) {
            log.warn("获取文件类型异常：", e);
            return null;
        }
    }

    /**
     * 获取文件类型
     *
     * @param inputStream 文件流
     * @param fileName 文件名称
     * @return 文件类型
     */
    public static String getMimeType(InputStream inputStream, String fileName) {
        try {
            Metadata metadata = new Metadata();
            AutoDetectParser parser = new AutoDetectParser();
            parser.setParsers(new HashMap<MediaType, Parser>(0));
            metadata.add(TikaMetadataKeys.RESOURCE_NAME_KEY, fileName);
            parser.parse(inputStream, new DefaultHandler(), metadata, new ParseContext());
            return metadata.get(HttpHeaders.CONTENT_TYPE);
        } catch (Exception e) {
            log.warn("获取文件类型异常：", e);
            return null;
        }
    }

    /**
     * 保存文件
     *
     * @param inputStream 文件流
     * @param baseUrl     保存根路径
     * @param fileName    文件名称
     * @return 文件路径
     */
    public static String uploadFile(InputStream inputStream, String baseUrl, String fileName) {

        if (inputStream == null) {
            return "";
        }
        fileName = Long.toString(System.currentTimeMillis(), 32) + "-" + fileName;
        // 输出的文件流保存到本地文件
        File tempFile = new File(baseUrl);
        if (!tempFile.exists()) {
            if (!tempFile.mkdirs()) {
                return "";
            }
        }
        String filePath = tempFile.getPath() + "/" + fileName;
        OutputStream os = null;
        try {
            if (isImage(inputStream, fileName)) {
                createThumbnail(ImageIO.read(inputStream), filePath);
            } else {
                // 保存文件
                // 1K的数据缓冲
                byte[] bs = new byte[1024 * 30];
                // 读取到的数据长度
                int len;

                os = new FileOutputStream(filePath);
                // 开始读取
                while ((len = inputStream.read(bs)) != -1) {
                    os.write(bs, 0, len);
                }
                return fileName;
            }
        } catch (Exception e) {
            log.error("保存文件异常：", e);
        } finally {
            // 完毕，关闭所有链接
            try {
                if (os != null) {
                    os.close();
                }
                inputStream.close();
            } catch (IOException e) {
                log.error("关闭IO流异常：", e);
            }
        }
        return "";
    }

    /**
     * 删除文件及文件加
     *
     * @param file-需要删除的文件文件
     * @return boolean
     */
    public static boolean deleteFile(File file) {

        if (Objects.isNull(file)) {
            return false;
        }
        // 如果dir对应的文件不存在
        if (!file.exists()) {
            return false;
        }
        if (file.isFile()) {
            return file.delete();
        }
        // 删除文件夹下的所有文件(包括子目录)
        File[] files = file.listFiles();
        if(files == null){
            return file.delete();
        }
        for (int i = 0; i < files.length; i++) {
            // 删除子文件
            if (!deleteFile(files[i])) {
                return false;
            }
        }
        // 删除当前目录
        return file.delete();
    }

    public static boolean deleteFile(String path) {
        if (Strings.isNullOrEmpty(path)) {
            return false;
        }
        File file = new File(path);
        return deleteFile(file);
    }
}
